
#include "bdcloud.h"

using namespace std;


size_t BdCloud::receive_data(void *contents, size_t size, size_t nmemb, void *stream){
    string *str = (string*)stream;
    (*str).append((char*)contents, size*nmemb);
    return size * nmemb;
}



CURLcode BdCloud::httpGet(const std::string & strUrl, std::string & strResponse,int nTimeout){
    CURLcode res;
    CURL* pCURL = curl_easy_init();

    if (pCURL == NULL) {
        return CURLE_FAILED_INIT;
    }

    curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(pCURL, CURLOPT_NOSIGNAL, 1L);
    curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);
    curl_easy_setopt(pCURL, CURLOPT_NOPROGRESS, 1L);
    curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, receive_data);
    curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse);
    res = curl_easy_perform(pCURL);
    curl_easy_cleanup(pCURL);
    return res;
}

CURLcode BdCloud::httpPost(const std::string & strUrl, std::string szJson,std::string & strResponse,int nTimeout){
    CURLcode res;
    char szJsonData[szJson.length() + 1];
    memset(szJsonData, 0, sizeof(szJsonData));
    strcpy(szJsonData, szJson.c_str());
    CURL* pCURL = curl_easy_init();
    struct curl_slist* headers = NULL;
    if (pCURL == NULL) {
        return CURLE_FAILED_INIT;
    }

    CURLcode ret;
    ret = curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());
//    std::cout << ret << std::endl;

    ret = curl_easy_setopt(pCURL, CURLOPT_POST, 1L);
    headers = curl_slist_append(headers,"content-type:application/json");

    ret = curl_easy_setopt(pCURL, CURLOPT_HTTPHEADER, headers);

    ret = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDS, szJsonData);
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    ret = curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);

    ret = curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, receive_data);

    ret = curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse);

    // ignore ssl
    curl_easy_setopt(pCURL, CURLOPT_SSL_VERIFYPEER, 0L);

    res = curl_easy_perform(pCURL);
    curl_easy_cleanup(pCURL);
    return res;
}

//从文件读入到string里
std::string BdCloud::readFileIntoString(const std::string filename)
{
    ifstream ifile(filename.c_str());
    //将文件读入到ostringstream对象buf中
    ostringstream buf;
    char ch;
    while(buf&&ifile.get(ch))
    buf.put(ch);
    //返回与流对象buf关联的字符串
    return buf.str();
}
  

CURLcode BdCloud::getToken(std::string & strToken){
  strToken = "";
  std::string strResponse;
  char bdCloudTokenFullUrl[1024];
  sprintf(bdCloudTokenFullUrl,"%s?grant_type=client_credentials&client_id=%s&client_secret=%s",this->bdCloudTokenUrl.c_str(),this->bdCloudAK.c_str(),this->bdCloudSK.c_str());
  CURLcode nRes = this->httpPost(bdCloudTokenFullUrl, "", strResponse,300);

  if (nRes != CURLE_OK){
    return nRes;
  }


  Json::CharReaderBuilder b;
  Json::CharReader* reader(b.newCharReader());
  Json::Value root;
  JSONCPP_STRING errs;
  bool ok = reader->parse(strResponse.c_str(), strResponse.c_str() + strResponse.length(), &root, &errs);

  if (ok && errs.size() == 0){
      strToken = root["access_token"].asString();
  }
   else{
       printf("Fail to parse token\n");
  }

  delete reader;

  return nRes;
}

CURLcode BdCloud::recognizeText(const std::string file,std::string & strText,const std::string strToken){
    strText = "";
    std::string strResponse;


    //todo 判断文件是否存在

    //base64加密
    std::string strFileContentBase64 = base64_encode(this->readFileIntoString(file));
    //url encode
    char * fileContentEncode = curl_escape(strFileContentBase64.c_str(), strFileContentBase64.size());
    //printf("%s xxx\n", fileContentEncode);
    // 参数为:image=base64(图片内容)
    char textParams[strlen(fileContentEncode) + 10];
    sprintf(textParams,"image=%s", fileContentEncode);


    std::string textParamsStr = textParams;

    //sprintf(szJson,"image=%s", strFileContentBase64.c_str());
    char bdCloudTextFullUrl[1024];
    sprintf(bdCloudTextFullUrl,"%s?access_token=%s", this->bdCloudTextUrl.c_str(), strToken.c_str());
    CURLcode nRes = this->httpPost(bdCloudTextFullUrl, textParamsStr, strResponse,300);
    if (nRes != CURLE_OK){
      return nRes;
    }

    Json::CharReaderBuilder b;
    Json::CharReader* reader(b.newCharReader());
    Json::Value root;
    JSONCPP_STRING errs;
    bool ok = reader->parse(strResponse.c_str(), strResponse.c_str() + strResponse.length(), &root, &errs);
 
    if (ok && errs.size() == 0)
    {
        if (root["words_result_num"].asInt() > 0){
            strText = root["words_result"][0]["words"].asString();
        }
        else{
            printf("Fail to recognizeText. res=%s\n", strResponse.c_str());
        }
        //printf("\n xxxx = %s \n" ,  root["result"]["words_block_list"][0]["words"].asString().c_str());
     }
     else{
         printf("Fail to parse. res = %s\n", strResponse.c_str());
     }

    delete reader;

    return nRes;
}
